﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Globalization;
using System.IO;

namespace GBPVRLibrary.MetadataLibrary.TheTVDBInterface
{
    public class TheTVDBSeries : TheTVDBItem
    {
        public enum EpisodeOrderType { Aired, DVD }
        /*
         <Series>
            <seriesid>71035</seriesid>
            <language>en</language>
            <SeriesName>Angel</SeriesName>
            <banner>graphical/71035-g3.jpg</banner>
            −
            <Overview>
            "If you need help, then look no further. Angel Investigations is the best. Our rats are low... (What? It says "rats." Sorry.) Ahem... our rates are low, but our standards are high. When the chips are down, and you're at the end of your rope you need someone that you can count on. And that's what you'll find here -- someone that will go all the way, no matter what. So don't lose hope. Come on over to our offices and you'll see that there's still heroes in this world."

            For over two centuries, Angelus was one of the most vicious vampires ever to walk the earth. Then he killed the wrong girl, and her grieving Gypsy family cursed the vampire with the return of his soul, causing him to suffer with remorse for all the hundreds of innocents that he had killed through the years. Now he goes by the name Angel, and he fights to protect the helpless from those who would prey upon them as he himself once did.

            After three years of living in Sunnydale, fighting alongside his girlfriend Buffy, Angel has moved to Los Angeles to continue the good fight. Aided by a few old friends and some new ones, Angel must take on vampires, demons, lawyers, and all of the other dark forces that Los Angeles has to offer.
            </Overview>
            <FirstAired>1999-10-05</FirstAired>
            <IMDB_ID>tt0162065</IMDB_ID>
            <zap2it_id>SH317395</zap2it_id>
            <id>71035</id>
        </Series>
         */

        public TheTVDBSeries() { this.EpisodeOrder = EpisodeOrderType.Aired; }

        public int Id { get; set; }
        public string Language { get; set; }
        public string BannerUrl { get; set; }
        public string Overview { get; set; }
        public DateTime? FirstAired { get; set; }
        public string ImdbId { get; set; }
        public string Zap2ItId { get; set; }
        public List<string> Genre { get; set; }
        public double? Rating { get; set; }
        public TimeSpan? Duration { get; set; }
        public EpisodeOrderType EpisodeOrder { get; set; }

        public XElement ToElement()
        {
            return new XElement("Series",
                                new XElement("seriesid", this.Id),
                                new XElement("language", this.Language),
                                new XElement("SeriesName", this.Name),
                                new XElement("Overview", this.Overview),
                                new XElement("FirstAired", this.FirstAired != null ? this.FirstAired.Value.ToString("yyyy-MM-dd") : ""),
                                new XElement("IMDB_ID", this.ImdbId),
                                new XElement("Zap2ItId", this.ImdbId),
                                new XElement("id", this.Id),
                                new XElement("EpisodeOrder", this.EpisodeOrder.ToString())
                               );
        }

        /// <summary>
        /// Saves TheTVDBSeries information to a path on the system
        /// </summary>
        /// <param name="Path">the path to save the information to</param>
        public void SaveToPath(string Path)
        {
            try
            {
                using (StreamWriter writer = new StreamWriter(String.Format(@"{0}\TheTVDBSeries.xml", Path)))
                {
                    writer.Write(this.ToElement().ToString());
                }
                GBPVRLibrary.UtilityLibrary.LogWriter.Log(String.Format(@"Saved TheTVDB Series information at '{0}\TheTVDBSeries.xml'", Path));
            }
            catch (Exception ex)
            {
                GBPVRLibrary.UtilityLibrary.LogWriter.Log(String.Format(@"Failed to save TheTVDB Series information at '{0}\TheTVDBSeries.xml' - {1}", Path, Environment.NewLine + ex.Message));
            }
        }

        public static TheTVDBSeries ParseSeries(XDocument Document)
        {
            try
            {
                return new TheTVDBSeries()
                {
                    Id = int.Parse(Document.Element("Series").Element("id").Value),
                    Language = Document.Element("Series").Element("language").Value,
                    Name = Document.Element("Series").Element("SeriesName").Value,
                    Overview = Document.Element("Series").Element("Overview").Value,
                    FirstAired = String.IsNullOrEmpty(Document.Element("Series").Element("FirstAired").Value) ? null : DateTime.ParseExact(Document.Element("Series").Element("FirstAired").Value, "yyyy-MM-dd", new CultureInfo("en-us")) as DateTime?,
                    ImdbId = Document.Element("Series").Element("IMDB_ID").Value,
                    Zap2ItId = Document.Element("Series").Element("Zap2ItId").Value,
                    EpisodeOrder = Document.Element("Series").Element("EpisodeOrder") == null ? EpisodeOrderType.Aired : (EpisodeOrderType)Enum.Parse(typeof(EpisodeOrderType), Document.Element("Series").Element("EpisodeOrder").Value)
                };
            }
            catch (Exception) { return null; }
        }

        public static TheTVDBSeries LoadSeries(string Mirror, int SeriesId, string Language)
        {
            string Url = String.Format("{0}/api/{1}/series/{2}/{3}.xml", Mirror, TheTVDB.APIKey, SeriesId, Language);
            XDocument doc = TheTVDB.LoadDocument(Url);
            return LoadSeries(doc.Element("Data").Element("Series"), Mirror);
        }

        /// <summary>
        /// Loads a TheTVDBSeries information from a Path on the system (cannot be a file)
        /// </summary>
        /// <param name="Path">the path to load TheTVDBSeries information from</param>
        /// <returns>the TheTVDBSeries information if found</returns>
        public static TheTVDBSeries LoadSeriesFromPath(string Path)
        {
            try
            {
                using (StreamReader reader = new StreamReader(String.Format(@"{0}\TheTVDBSeries.xml", Path)))
                {
                    XElement element = XElement.Parse(reader.ReadToEnd());
                    return TheTVDBSeries.LoadSeries(element, null);
                }
            }
            catch (Exception) { return null; }
        }
                
        public static TheTVDBSeries LoadSeries(XElement Element, string Mirror)
        {
            if(Mirror == null)
                Mirror = "";
            else
                Mirror += "/";
            return new TheTVDBSeries()
                    {
                        Id = Element.Element("seriesid") != null ? int.Parse(Element.Element("seriesid").Value) : int.Parse(Element.Element("id").Value),
                        Language = Element.Element("language") == null ? null : Element.Element("language").Value,
                        Name = Element.Element("SeriesName").Value,
                        BannerUrl = Element.Element("banner") == null ? null : Mirror + Element.Element("banner").Value,
                        FirstAired = Element.Element("FirstAired") == null ? null : DateTime.ParseExact(Element.Element("FirstAired").Value, "yyyy-MM-dd", new CultureInfo("en-us")) as DateTime?,
                        Overview = Element.Element("Overview") == null ? null : Element.Element("Overview").Value,
                        ImdbId = Element.Element("IMDB_ID") == null ? null : Element.Element("IMDB_ID").Value,
                        Zap2ItId = Element.Element("zap2it_id") == null ? null : Element.Element("zap2it_id").Value,
                        Unit = Element.Element("FirstAired") == null ? "" : Element.Element("FirstAired").Value,
                        Genre = Element.Element("Genre") == null ? null : Element.Element("Genre").Value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
                        Duration = Element.Element("Runtime") == null || String.IsNullOrEmpty(Element.Element("Runtime").Value) ? null : new TimeSpan(0, int.Parse(Element.Element("Runtime").Value), 0) as TimeSpan?,
                        Rating = Element.Element("Rating") == null || String.IsNullOrEmpty(Element.Element("Rating").Value) ? null : (double.Parse(Element.Element("Rating").Value) / 10) as double?,
                        EpisodeOrder = Element.Element("EpisodeOrder") == null ? EpisodeOrderType.Aired : (EpisodeOrderType)Enum.Parse(typeof(EpisodeOrderType), Element.Element("EpisodeOrder").Value)
                    };
        }
    }
}
